package service

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"golang.org/x/net/context"
	"lot_admin_api/api"
	"lot_admin_api/internal/consts"
	"lot_admin_api/internal/dao"
	"lot_admin_api/internal/model"
	"lot_admin_api/utility/response"
)

type sAuth struct {
}

var insAuth = sAuth{}

func Auth() *sAuth {
	return &insAuth
}

//AddAuth 添加权限
func (s *sAuth) AddAuth(ctx context.Context, req *api.AddAuthReq) (id int64, err error) {
	r := g.RequestFromCtx(ctx)
	var findAuthOne *model.AuthInfo
	if req.ParentId == 0 {
		if findAuth, _ := dao.LotAuth.Ctx(ctx).Where("parent_id", 0).One(); findAuth != nil {
			response.JsonExit(r, consts.HTTPInternalServer.Code(), "权限只能存在一个根")
		}
	}
	// 判断code是否重复
	err = dao.LotAuth.Ctx(ctx).Where("auth_code", req.AuthCode).Scan(&findAuthOne)
	if findAuthOne != nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "code重复:"+findAuthOne.AuthCode)
	}
	saveInfo, err := dao.LotAuth.Ctx(ctx).Save(req)
	id, err = saveInfo.LastInsertId()
	return id, err
}

// UpdateAuth 编辑权限
func (s *sAuth) UpdateAuth(ctx context.Context, req *api.UpdateAuthReq) (id int64, err error) {
	// 检验权限是否存在
	_, err = s.ShowAuth(ctx, req.Id)
	_, err = dao.LotAuth.Ctx(ctx).OmitEmpty().Data(&req).Where("id", req.Id).Update()
	return req.Id, err
}

// DeleteAuth 删除权限
func (s *sAuth) DeleteAuth(ctx context.Context, req *api.DeleteAuthReq) (id int64, err error) {
	// 检验权限是否存在
	_, err = s.ShowAuth(ctx, req.Id)
	r := g.RequestFromCtx(ctx)
	if searchChildList, _ := dao.LotAuth.Ctx(ctx).Where("parent_id", req.Id).All(); searchChildList.Len() != 0 {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "不能删除,该权限有"+gconv.String(searchChildList.Len())+"个子权限")
	}
	_, err = dao.LotAuth.Ctx(ctx).OmitEmpty().Data(&req).Where("id", req.Id).Delete()
	return req.Id, err
}

// GetInfoAuth 查询权限详情
func (s *sAuth) GetInfoAuth(ctx context.Context, req *api.GetInfoAuthReq) (findOne *model.AuthTreeInfoRes, err error) {
	findOne, err = s.ShowAuth(ctx, req.Id)
	return findOne, err
}

// GetTreeAuth 查询权限树结构
func (s *sAuth) GetTreeAuth(ctx context.Context, req *api.GetTreeAuthReq) (findOne *model.AuthTreeInfoRes, err error) {
	var tree []model.AuthTreeInfoRes
	// 检验权限是否存在
	findOne, err = s.ShowAuth(ctx, req.Id)
	// 权限的递归查询sql
	searchSql := `
				WITH RECURSIVE tree_cte as
				(
    				select * from lot_auth where parent_id = ?
    				UNION ALL
					select t.* from lot_auth t inner join tree_cte tcte on t.parent_id = tcte.id
				)
				SELECT * FROM tree_cte WHERE deleted_at IS NULL;
			`
	// 通过原生sql 查询数组
	searchInfo, err := g.DB().GetAll(ctx, searchSql, g.Slice{req.Id})
	// 请求获得参数装换 res 格式
	_ = gconv.Scan(searchInfo, &tree)
	//将一维数组转换为递归数组
	tree = s.CreateTree(tree, findOne.Id)
	findOne.Children = tree
	return findOne, err
}

// ShowAuth 判断有没有当前权限
func (s *sAuth) ShowAuth(ctx context.Context, id int64) (searchInfo *model.AuthTreeInfoRes, err error) {
	r := g.RequestFromCtx(ctx)
	search := g.Map{
		"id": id,
	}
	err = dao.LotAuth.Ctx(ctx).Where(search).Scan(&searchInfo)
	if searchInfo == nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "没有当前权限")
	}
	return searchInfo, err
}

// CreateTree  tree创建树状结构  nodes 一维树结构  ParentId第一层的对比的父级id
func (s *sAuth) CreateTree(nodes []model.AuthTreeInfoRes, ParentId int64) []model.AuthTreeInfoRes {
	tree := make([]model.AuthTreeInfoRes, 0)
	var roots, children []model.AuthTreeInfoRes
	for _, v := range nodes {
		if v.ParentId == ParentId {
			roots = append(roots, v)
		} else {
			children = append(children, v)
		}
	}
	for _, v := range roots {
		var rootNode *model.AuthTreeInfoRes
		_ = gconv.Scan(v, &rootNode)
		s.Recursion(rootNode, children)
		tree = append(tree, *rootNode)
	}
	return tree
}

// Recursion  递归处理权限tree
func (s *sAuth) Recursion(rootNode *model.AuthTreeInfoRes, children []model.AuthTreeInfoRes) {
	id := rootNode.Id
	for _, v := range children {
		if id == v.ParentId {
			var childNode *model.AuthTreeInfoRes
			_ = gconv.Scan(v, &childNode)
			s.Recursion(childNode, children)
			rootNode.Children = append(rootNode.Children, *childNode)
		}
	}
}
